package com.ztsoft.user.utils;

import com.deepoove.poi.XWPFTemplate;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;


/**
 * @author yeting
 * @Descript TODO (利用freemark生成word及zip)
 * @date 2019年3月19日
 */
@Slf4j
@Component
public class ZipUtils {

    /**
     * 根据模板填充内容生成word
     * 调用方法参考下面的main方法，详细文档参考官方文档
     * Poi-tl模板引擎官方文档：http://deepoove.com/poi-tl/
     *
     * @param templatePath word模板文件路径
     * @param fileDir      生成的文件存放地址
     * @param fileName     生成的文件名,不带格式。假如要生成abc.docx，则fileName传入abc即可
     * @param paramMap     替换的参数集合
     * @return 生成word成功返回生成的文件的路径，失败返回空字符串
     */
    public static void createWord(String templatePath, String fileDir, String fileName, Map<String, String> paramMap) {

        Assert.notNull(templatePath, "word模板文件路径不能为空");
        Assert.notNull(fileDir, "生成的文件存放地址不能为空");
        Assert.notNull(fileName, "生成的文件名不能为空");

        // 生成的word格式
        String formatSuffix = ".docx";
        // 拼接后的文件名
        fileName = fileName + formatSuffix;

        // 生成的文件的存放路径
        if (!fileDir.endsWith("/")) {
            fileDir = fileDir + File.separator;
        }

        File dir = new File(fileDir);
        if (!dir.exists()) {

            dir.mkdirs();
        }

        String filePath = fileDir + fileName;
        // 读取模板templatePath并将paramMap的内容填充进模板，即编辑模板+渲染数据
        XWPFTemplate template = XWPFTemplate.compile(templatePath).render(paramMap);
        try {
            // 将填充之后的模板写入filePath
            template.writeToFile(filePath);
            template.close();
        } catch (Exception e) {

            e.printStackTrace();

        }

    }


    public void createFile(String template, String fileFullPath) {
        try {
            //创建文件
            File file = new File(fileFullPath);
            // 如果输出目标文件夹不存在，则创建
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }
            BufferedWriter writer = new BufferedWriter(new FileWriter(new File(fileFullPath), true));
            writer.write("\n" + template);
            writer.close();
        } catch (Exception e) {
            throw new RuntimeException("数据写入出错");
        }


    }


    /**
     * 生成zip文件,根据文件路径不带子文件夹(全局可用)
     *
     * @param zipfullPath   压缩后的zip文件全路径
     * @param fileFullPaths 压缩前的文件全路径数组
     */
    public void createZip(String zipfullPath, List<String> fileFullPaths) {
        InputStream inputStream = null;
        ZipOutputStream zip = null;

        try {
            File files = new File(zipfullPath);
            if (!files.getParentFile().exists()) {
                files.getParentFile().mkdirs();
            }
            zip = new ZipOutputStream(new FileOutputStream(zipfullPath));
//            zip.setEncoding("gbk");

            for (String fullPath : fileFullPaths) {
//                log.info("【createZip:fullPath】：==>" + fullPath);

           /*     if(StringUtil.isNullOrEmpty(fullPath)) {
                    continue;
                }*/

                //创建文件
                File file = new File(fullPath);
                String fileName = file.getName();

                //读文件流
                inputStream = new BufferedInputStream(new FileInputStream(file));
                byte[] buffer = new byte[inputStream.available()];
                inputStream.read(buffer);
                inputStream.close();

                //将读取的文件输出到zip中
                zip.putNextEntry(new ZipEntry(fileName));
                zip.write(buffer);
                zip.closeEntry();
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

            try {
                if (zip != null) {
                    zip.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }

    /**
     * 生成的zip文件带子文件夹(全局可用)
     *
     * @param zipfullPath  压缩后的zip文件全路径
     * @param fileFullPath 压缩前的文件全路径
     * @param isKeepDirStr 是否保留原来的目录结构,true:保留目录结构; false:所有文件跑到压缩包根目录下(注意：不保留目录结构可能会出现同名文件,会压缩失败)
     */
    public void createZip(String zipfullPath, String fileFullPath, boolean isKeepDirStr) {
        InputStream inputStream = null;
        ZipOutputStream zip = null;

        try {
            zip = new ZipOutputStream(new FileOutputStream(zipfullPath));
//            zip.setEncoding("gbk");

            File file = new File(fileFullPath);

            compressZip(inputStream, zip, file, file.getName(), isKeepDirStr);//递归压缩

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

            try {
                if (zip != null) {
                    zip.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }

    /**
     * 递归压缩方法(仅限于此类中用于压缩zip文件)
     *
     * @param inputStream  输入流
     * @param zip          zip输出流
     * @param sourceFile   源文件
     * @param fileName     文件夹名或文件名
     * @param isKeepDirStr 是否保留原来的目录结构,true:保留目录结构; false:所有文件跑到压缩包根目录下(注意：不保留目录结构可能会出现同名文件,会压缩失败)
     * @throws Exception
     */
    private void compressZip(InputStream inputStream, ZipOutputStream zip, File sourceFile, String fileName, boolean isKeepDirStr) throws Exception {
//        log.info("【compressZip:sourceFile】：==>" + sourceFile.getPath());
//        log.info("【compressZip:fileName】：==>" + fileName);

        if (sourceFile.isFile()) {
            //读文件流
            inputStream = new BufferedInputStream(new FileInputStream(sourceFile));
            byte[] buffer = new byte[inputStream.available()];
            inputStream.read(buffer);
            inputStream.close();

            //将读取的文件输出到zip中
            zip.putNextEntry(new ZipEntry(fileName));
            zip.write(buffer);
            zip.closeEntry();
        } else {
            File[] listFiles = sourceFile.listFiles();
            if (listFiles == null || listFiles.length == 0) {
                // 需要保留原来的文件结构时,需要对空文件夹进行处理
                if (isKeepDirStr) {
                    zip.putNextEntry(new ZipEntry(fileName + "/"));//空文件夹的处理
                    zip.closeEntry();// 没有文件，不需要文件的copy
                }
            } else {
                for (File file : listFiles) {
                    // 判断是否需要保留原来的文件结构,注意：file.getName()前面需要带上父文件夹的名字加一斜杠,不然最后压缩包中就不能保留原来的文件结构,即：所有文件都跑到压缩包根目录下了
                    if (isKeepDirStr) {
                        compressZip(inputStream, zip, file, fileName + "/" + file.getName(), isKeepDirStr);
                    } else {
                        compressZip(inputStream, zip, file, file.getName(), isKeepDirStr);
                    }
                }
            }
        }
    }

    /**
     * 下载生成的文件(全局可用)
     *
     * @param fullPath 全路径
     * @param response
     */
    public void downLoadFile(String fullPath, HttpServletResponse response) {
//        log.info("【downLoadFile:fullPath】：==>" + fullPath);

        InputStream inputStream = null;
        OutputStream outputStream = null;

        try {
            //创建文件
            File file = new File(fullPath);
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }
            String fileName = file.getName();
            //读文件流
            inputStream = new BufferedInputStream(new FileInputStream(file));
            byte[] buffer = new byte[inputStream.available()];
            inputStream.read(buffer);

            //清空响应
//            response.reset();
            //           response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
            response.setHeader("Access-Control-Allow-Headers", "Content-Type");
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/x-zip-compressed; charset=utf-8");
//            response.setContentType("application/octet-stream; charset=utf-8");
            // response.setContentType("application/msword");
            response.setHeader("Content-Disposition", "attachment; filename=" + new String(fileName.getBytes(), "ISO8859-1"));
            response.setHeader("Content-Length", String.valueOf(file.length()));
            response.setContentLength(Integer.parseInt(String.valueOf(file.length())));
 /*           long length = file.length();
            System.out.println(length);
            String header = response.getHeader("Content-Length");
            System.out.println(header);*/
            //写文件流
            outputStream = new BufferedOutputStream(response.getOutputStream());

            outputStream.write(buffer);
            outputStream.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }

    /**
     * 下载网络文件到本地(主要用于下载简历附件)
     *
     * @param urlAddress   网络url地址,为空时直接返回
     * @param fileFullPath 文件全路径
     */
    public void createFromUrl(String urlAddress, String fileFullPath) {
//        log.info("【service:开始下载网络文件】:==> 网上文件地址：" + urlAddress + "文件保存路径:" + fileFullPath);

       /* if(StringUtil.isNullOrEmpty(urlAddress)) {
            return ;
        }*/

        DataInputStream dataInputStream = null;
        FileOutputStream fileOutputStream = null;
        try {

            URL url = new URL(urlAddress);

            dataInputStream = new DataInputStream(url.openStream());//打开网络输入流

            //创建文件
            File file = new File(fileFullPath);
            // 如果输出目标文件夹不存在，则创建
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }

            fileOutputStream = new FileOutputStream(file);//建立一个新的文件

            byte[] buffer = new byte[1024];
            int length;

            while ((length = dataInputStream.read(buffer)) > 0) {//开始填充数据
                fileOutputStream.write(buffer, 0, length);
            }

            fileOutputStream.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (dataInputStream != null) {
                    dataInputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            try {
                if (fileOutputStream != null) {
                    fileOutputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 删除文件及文件夹
     *
     * @param path
     * @return
     */
    public boolean delAllFile(String path) {
        boolean flag = false;
        File file = new File(path);
        if (!file.exists()) {
            return flag;
        }
        if (!file.isDirectory()) {
            return flag;
        }
        String[] tempList = file.list();
        File temp;
        for (int i = 0; i < tempList.length; i++) {
            if (path.endsWith(File.separator)) {
                temp = new File(path + tempList[i]);
            } else {
                temp = new File(path + File.separator + tempList[i]);
            }
            if (temp.isFile()) {
                temp.delete();
                temp.getParentFile().delete();
            }
            if (temp.isDirectory()) {
                delAllFile(path + "/" + tempList[i]);//先删除文件夹里面的文件
                delFolder(temp.getPath());
                if (tempList.length == 0) {
                    flag = true;
                }
            }
        }
        return flag;
    }

    public void delFolder(String folderPath) {
        try {
            delAllFile(folderPath); //删除完里面所有内容
            String filePath = folderPath;
            File myFilePath = new File(filePath);
            myFilePath.delete(); //删除空文件夹
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void delFile(String filePathAndName) {
        try {
            String filePath = filePathAndName;
            filePath = filePath;
            File myDelFile = new File(filePath);
            myDelFile.delete();
        } catch (Exception e) {
            System.out.println("删除文件操作出错");
            e.printStackTrace();
        }
    }

}
